package com.unicom.office.impl;

import com.unicom.office.config.*;
import com.unicom.office.type.*;
import com.unicom.office.var.*;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.*;

public class OfficeConfigForJSONorXML extends OfficeConfig {

    public OfficeConfigForJSONorXML() {
    }

    public OfficeConfigForJSONorXML(String configPath) {
        super(configPath);
        parseConfigFile(configPath);
    }

    public void parseConfigFile(String configPath) {
        if(configPath.toLowerCase().contains(".xml")) {
            parseXMLFile(configPath);
        }else if(configPath.toLowerCase().contains(".json")){
            parseJSONFile(configPath);
        }else {
            throw new RuntimeException("不支持的配置文件格式");
        }
    }

    public void parseJSONFile(String configPath){

    }

    private Element useDom4JReadXml(String soucePath){
        try {
            File file = new File(soucePath);
            SAXReader read = new SAXReader();
            org.dom4j.Document doc = read.read(file);
            Element root = doc.getRootElement();
            return root;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public void parseXMLFile(String configPath){
        org.dom4j.Element ele = useDom4JReadXml(configPath);
//        ele = ele.element("office-template-config");
//
//        if(ele == null) {
//            throw new RuntimeException("未发现office-template-config节点");
//        }

        Element types = ele.element("custom-types");
        if(types != null) {
            for (Iterator iterator = types.elementIterator(); iterator.hasNext();){
                org.dom4j.Element next = (org.dom4j.Element)iterator.next();
                register(parseTypeElement(next));
            }
        }

        Element vars = ele.element("vars");
        if(vars != null) {
            for (Iterator iterator = vars.elementIterator(); iterator.hasNext();){
                org.dom4j.Element next = (org.dom4j.Element)iterator.next();
                register(parseVarElement(next));
            }
        }
    }

    private String getElementStringValue(org.dom4j.Element element, String name){
        Element element1 = element.element(name);
        if(element1 != null) {
            return element1.getTextTrim();
        }else {
            return element.attributeValue(name);
        }
    }

    private TypeItem parseTypeElement(org.dom4j.Element element){
        String name = getElementStringValue(element, "name");
        if(element.getName() == "list"){
            String typeName = element.attributeValue("itemType");
            TypeItem typeItem = getTypeItem(typeName);
            ListTypeItem listTypeItem = new ListTypeItem(name, typeItem);
            return listTypeItem;
        }else if(element.getName() == "object") {
            org.dom4j.Element props = element.element("props");

            ObjectTypeItem objectTypeItem = new ObjectTypeItem(name);

            if(props != null){
                for(Iterator iterator = props.elementIterator(); iterator.hasNext();){
                    org.dom4j.Element next = (org.dom4j.Element)iterator.next();
                    VarItem prop = parseVarElement(next);
                    objectTypeItem.addProp(prop.getName(), prop);
                }
            }

            return objectTypeItem;
        }else {
            return null;
        }
    }

    private VarItem parseVarElement(org.dom4j.Element element){
        String name = getElementStringValue(element, "name");
        String type = element.getName();
        VarItem result = null;

        if ("string".equals(type)) {
            StringVarItem stringVarItem = new StringVarItem(name);

            String defaultValue = getElementStringValue(element, "defaultValue");
            if(defaultValue != null){
                stringVarItem.setDefaultValue(defaultValue);
            }

            result = stringVarItem;
        }else if("boolean".equals(type)){
            BooleanVarItem booleanVarItem = new BooleanVarItem(name);

            String defaultValue = getElementStringValue(element, "defaultValue");
            if(defaultValue != null){
                booleanVarItem.setDefaultValue(defaultValue);
            }

            result = booleanVarItem;
        }else if("list".equals(type)) {
            String itemType = getElementStringValue(element, "itemType");
            TypeItem typeItem = getTypeItem(itemType);
            ListVarItem listVarItem = new ListVarItem(name, typeItem);
            org.dom4j.Element defaultValueElement = element.element("default-value");
            if(defaultValueElement != null){
                listVarItem.setDefaultValue(parseDefaultValueElement(defaultValueElement, listVarItem.getTypeItem()));
            }

            result = listVarItem;
        }else if("object".equals(type)) {
            String itemType = getElementStringValue(element, "type");
            TypeItem typeItem = getTypeItem(itemType);
            if(!(typeItem instanceof ObjectTypeItem)) {
                throw new RuntimeException("指定类型不是对象类型");
            }
            ObjectVarItem objectVarItem = new ObjectVarItem(name, (ObjectTypeItem) typeItem);

            org.dom4j.Element defaultValueElement = element.element("default-value");
            if(defaultValueElement != null){
                objectVarItem.setDefaultValue(parseDefaultValueElement(defaultValueElement, objectVarItem.getTypeItem()));
            }

            result = objectVarItem;
        }else if("number".equals(type)){
            NumberVarItem numberVarItem = new NumberVarItem(name);

            String defaultValue = getElementStringValue(element, "defaultValue");
            if(defaultValue != null){
                numberVarItem.setDefaultValue(Double.valueOf(defaultValue));
            }

            result = numberVarItem;
        }else {
            throw new RuntimeException("不支持的变量类型");
        }

        String description = getElementStringValue(element, "description");
        if(description != null){
            result.setDescription(description);
        }

        return result;
    }

    private Object parseDefaultValueElement(org.dom4j.Element element, TypeItem type){
        Object defaultValue = null;

        if(type instanceof ObjectTypeItem) {
            if(element.element("object") == null) {
                throw new RuntimeException("未提供有效默认值,对象未用object标签包起来");
            }
            ObjectTypeItem objectTypeItem = (ObjectTypeItem)type;
            Map<String, Object> obj = new HashMap<String, Object>();
            for(Iterator iterator = element.element("object").elementIterator("prop"); iterator.hasNext();){
                org.dom4j.Element next = (org.dom4j.Element)iterator.next();
                String propName = getElementStringValue(next, "name");
                if(objectTypeItem.getProps().containsKey(propName)){
                    VarItem propType = objectTypeItem.getProps().get(propName);
                    Object value = parseDefaultValueElement(next, propType.getTypeItem());
                    obj.put(propName, value);
                }
            }
            defaultValue = obj;
        }else if(type instanceof StringTypeItem){
            String str = getElementStringValue(element, "value");
            if(str == null){
                str = element.getTextTrim();
            }
            defaultValue = str;
        }else if(type instanceof NumberTypeItem){
            String str = getElementStringValue(element, "value");
            if(str == null){
                str = element.getTextTrim();
            }
            defaultValue = Double.valueOf(str);
        }else if(type instanceof ListTypeItem){
            if(element.element("list") == null) {
                throw new RuntimeException("未提供有效默认值，数组未用list标签包起来");
            }
            List<Object> list = new ArrayList<Object>();
            ListTypeItem listTypeItem = (ListTypeItem) type;
            for(Iterator iterator = element.element("list").elementIterator("item"); iterator.hasNext();){
                org.dom4j.Element next = (org.dom4j.Element)iterator.next();
                Object value = parseDefaultValueElement(next, listTypeItem.getItemType());
                list.add(value);
            }
            defaultValue = list;
        }

        return defaultValue;
    }
}
